#include "ring_mem.h"
#include "common.h"

bool test_case_push(RingMem &ring_mem,
    size_t r1, size_t w1, size_t use1,
    char *data1, size_t len1,
    size_t r2, size_t w2, size_t use2,
    char *data2, size_t len2) {
  ring_mem.set_arr(10);
  ring_mem.set_r_w_user(r1, w1, use1);
  ring_mem.PushData(data1, len1);

  if (ring_mem.is_same(len2, data2, r2, w2, use2)) {
    return true;
  } else {
    ring_mem.printf_mem();
    std::cout << "failed:" << std::endl;
    std::cout << "should r=" << ring_mem.get_r()
              << ", w=" << ring_mem.get_w()
              << ", use=" << ring_mem.get_use()
              << std::endl;
    std::cout << "wrong  r=" << r2
              << ", w=" << w2
              << ", use=" << use2
              << std::endl;
    return false;
  }

  return true;
}

bool test_case_pop(RingMem &ring_mem,
    size_t r1, size_t w1, size_t use1,
    char *data1, size_t len1,
    size_t r2, size_t w2, size_t use2,
    char *data2, size_t len2) {
  ring_mem.set_arr(10);
  ring_mem.set_r_w_user(r1, w1, use1);
  ring_mem.PopData(data1, len1);

  if (ring_mem.is_same(len2, data2, r2, w2, use2)) {
    return true;
  } else {
    ring_mem.printf_mem();
    std::cout << "failed:" << std::endl;
    std::cout << "should r=" << ring_mem.get_r()
              << ", w=" << ring_mem.get_w()
              << ", use=" << ring_mem.get_use()
              << std::endl;
    std::cout << "wrong  r=" << r2
              << ", w=" << w2
              << ", use=" << use2
              << std::endl;
    return false;
  }

  return true;
}


int test1() {
  char data[10] = {0};
  for (size_t i = 0; i < ARR_SIZE(data); i++) {
    data[i] = static_cast<char>(i + 20);
  }

  size_t i_count = 0;
  size_t i_success = 0;

  RingMem ring_mem(10);
  { // case 1
    std::cout << "1---------------------------" << std::endl;
    char data_ret1[10] = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29};
    if (test_case_push(ring_mem,
        0, 0, 0, data, ARR_SIZE(data),
        0, 0, 10, data_ret1, 10) == true) {
      i_success++;
    }
    i_count++;
  }
  { // case 2
    std::cout << "2---------------------------" << std::endl;
    char data_ret1[10] = {10, 10, 10, 10, 10, 20, 21, 22, 23, 24};
    if (test_case_push(ring_mem,
        0, 5, 5, data, 5,
        0, 0, 10, data_ret1, ARR_SIZE(data_ret1)) == true) {
      i_success++;
    }
    i_count++;
  }
  { // case 3
    std::cout << "3---------------------------" << std::endl;
    char data_ret1[10] = {25, 26, 27, 10, 10, 20, 21, 22, 23, 24};
    if (test_case_push(ring_mem,
        3, 5, 2, data, 8,
        3, 3, 10, data_ret1, ARR_SIZE(data_ret1)) == true) {
      i_success++;
    }
    i_count++;
  }
  { // case 4
    std::cout << "4---------------------------" << std::endl;
    char data_ret1[10] = {20, 21, 22, 23, 24, 10, 10, 10, 10, 10};
    if (test_case_push(ring_mem,
        5, 0, 5, data, 5,
        5, 5, 10, data_ret1, ARR_SIZE(data_ret1)) == true) {
      i_success++;
    }
    i_count++;
  }
  { // case 5
    std::cout << "5---------------------------" << std::endl;
    char data_ret1[10] = {10, 10, 20, 21, 22, 23, 10, 10, 10, 10};
    if (test_case_push(ring_mem,
        6, 2, 6, data, 4,
        6, 6, 10, data_ret1, ARR_SIZE(data_ret1)) == true) {
      i_success++;
    }
    i_count++;
  }

  { // pop case 1
    std::cout << "6---------------------------" << std::endl;
    char data_ret1[10] = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
    if (test_case_pop(ring_mem,
        0, 0, 10, data, 10,
        0, 0, 0, data_ret1, ARR_SIZE(data_ret1)) == true) {
      i_success++;
    }
    i_count++;
  }
  { // pop case 2
    std::cout << "7---------------------------" << std::endl;
    char data_ret1[10] = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
    if (test_case_pop(ring_mem,
        0, 5, 5, data, 5,
        5, 5, 0, data_ret1, ARR_SIZE(data_ret1)) == true) {
      i_success++;
    }
    i_count++;
  }
  { // pop case 3
    std::cout << "8---------------------------" << std::endl;
    char data_ret1[10] = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
    if (test_case_pop(ring_mem,
        3, 7, 4, data, 4,
        7, 7, 0, data_ret1, ARR_SIZE(data_ret1)) == true) {
      i_success++;
    }
    i_count++;
  }
  { // pop case 4
    std::cout << "9---------------------------" << std::endl;
    char data_ret1[10] = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
    if (test_case_pop(ring_mem,
        5, 0, 5, data, 5,
        0, 0, 0, data_ret1, ARR_SIZE(data_ret1)) == true) {
      i_success++;
    }
    i_count++;
  }
  { // pop case 5
    std::cout << "10--------------------------" << std::endl;
    char data_ret1[10] = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
    if (test_case_pop(ring_mem,
        6, 2, 6, data, 6,
        2, 2, 0, data_ret1, ARR_SIZE(data_ret1)) == true) {
      i_success++;
    }
    i_count++;
  }

  std::cout << "success[" << i_success << "/" << i_count
            << "]" << std::endl;
  return 0;
}

int test2() {
  RingMem ring_mem(10);
  char data[10] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'h', 'j'};  
  char data_tmp[10] = {0};

  for (size_t k = 1; k <= 10; k++) {
    size_t i_total = 100; // push pop 100 times
    size_t i_success = 0;
    size_t push_pop_size = k;
    for (size_t i = 0; i < i_total; i++) {
      memset(data_tmp, 0, 10);
      ring_mem.PushData(data, push_pop_size);
      ring_mem.PopData(data_tmp, push_pop_size);
      size_t j = 0;
      for (j = 0; j < push_pop_size; j++) {
        if (data_tmp[j] != data[j]) {
          break;
        }
      }
      if (j == push_pop_size) {
        i_success++;
      }
    }
    std::cout << "success push_pop_size [" << push_pop_size << "]: [" << i_success << "/" << i_total
              << "]" << std::endl;
  }

  return 0;
}

// g++ test.cpp -Wall -Werror -Wextra -Wsign-conversion -Wconversion
int main() {
TIME_COST_START("test1")
  test1();
TIME_COST_END

TIME_COST_START("test2")
  test2();
TIME_COST_END
  return 0;
}

